package com.cloudeasy.area.authorize;

import com.cloudeasy.api.constant.SecurityConstant;
import com.cloudeasy.api.enums.MethodEnum;
import com.cloudeasy.api.enums.ResultCodeEnum;
import com.cloudeasy.api.exception.CloudEasyException;
import com.cloudeasy.api.vo.Result;
import com.cloudeasy.api.vo.user.PermissionVO;
import com.cloudeasy.area.client.ServerClient;
import com.cloudeasy.core.properties.SecurityProperties;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.*;

/**
 * 安全权限计算器，默认
 * 需要调用ServerClient获取权限信息，在依赖模块中调用会出问题--？
 */
@Component
public class SecurityPermissionEvaluator implements PermissionEvaluator {
    /**
     * 路径匹配器
     */
    private AntPathMatcher pathMatcher = new AntPathMatcher();
    /**
     * Server客户端
     */
    private final ServerClient serverClient;

    public SecurityPermissionEvaluator(ServerClient serverClient) {
        this.serverClient = serverClient;
    }

    /**
     * 判断逻辑
     *
     * @param authentication     认证
     * @param targetDomainObject 目标对象，这里传递进来的是HttpServletRequest对象
     * @param permission         统一拦截，该计算器中不会调用
     * @return 是否有权限访问
     */
    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        HttpServletRequest request = (HttpServletRequest) targetDomainObject;

        String username = (String) authentication.getPrincipal();

        // 如果是未认证的默认用户
        if (username.equals(SecurityConstant.DEFAULT_SECURITY_USERNAME)) {
            return false;
        }

        boolean hasPermission = false;

        Result<List<PermissionVO>> result = serverClient.getUserEnablePermission(username);
        if (result.getCode().equals(ResultCodeEnum.REMOTE_ERROR.getCode())) {
            throw new CloudEasyException(ResultCodeEnum.REMOTE_ERROR);
        }
        if (!result.getCode().equals(ResultCodeEnum.SUCCESS.getCode())) {
            throw new CloudEasyException(Objects.requireNonNull(ResultCodeEnum.get(result.getCode())));
        }

        // 获取到用户的权限
        Set<PermissionVO> permissionVOSet = new HashSet<>(result.getData());
        Map<String, PermissionVO> parentPermissionVO = new HashMap<>();
        for (PermissionVO permissionVO : permissionVOSet) {
            // 如果是总权限，添加进Map
            if (permissionVO.getParentId() == null) {
                parentPermissionVO.put(permissionVO.getParentId(), permissionVO);
                continue;
            }
            // 判断请求方式是否相同
            String method = MethodEnum.get(permissionVO.getMethod());
            boolean sameMethod = method == null || Objects.equals(request.getMethod(), method);
            // 如果请求方式不同，跳过
            if (!sameMethod) {
                continue;
            }
            // 如果url满足当前访问的url，或者拥有父权限，放行
            if (pathMatcher.match(permissionVO.getUrl(), request.getRequestURI()) || parentPermissionVO.containsKey(permissionVO.getParentId())) {
                hasPermission = true;
                break;
            }
        }
        return hasPermission;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        return false;
    }
}
